home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / allocwg.com / MEMUTIL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-10  |  10.5 KB  |  367 lines

  1. #ifndef MSC
  2.  
  3.     /*  Non-MSC Version  */
  4.  
  5. #if (defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM))
  6.  
  7.     /*  NOTE:  These procedures should only be used for
  8.                large data model programs (i.e., Compact, Large, Huge) */
  9.  
  10. #include <stddef.h>
  11. #include <stdlib.h>
  12. #include <dos.h>
  13. #include "alloc.h"
  14.  
  15. extern ATABLE  AllocationTable [] ;   /* Provide storage for block pointers */
  16. extern SUNIT   TABLESIZE          ;   /* Maximum allocation table size      */
  17. extern SUNIT   MBSize             ;   /* Default allocation block size      */
  18. extern SUNIT   NEntry             ;   /* Number of table entries            */
  19.  
  20. SUNIT *FindBlock ( Header, Size )
  21.  
  22.    HEADER *Header   ;
  23.    SUNIT   Size     ;
  24.  
  25. /*
  26.          +---------------------------------------+
  27.          |                                       |  
  28.          |  This procedure searches the given    |  
  29.          |  block (pointed to by Header) for     |  
  30.          |  a block large enough to hold 'Size'  |  
  31.          |  bytes.  If one is found, the block   |  
  32.          |  is set to 'in use' and it's address  |  
  33.          |  is returned.                         |  
  34.          |                                       |  
  35.          +---------------------------------------+
  36. */
  37.  
  38. {
  39.    SUNIT   *bptr    ;
  40.    SUNIT    offset  ;
  41.    SUNIT    bsize   ;
  42.    
  43.  
  44.    if ( Header->HeaderSize != HSIZE )
  45.       return ( NULL ) ;
  46.    
  47.       /*  Check if largest free block is large enough for allocation  */
  48.  
  49.    if ( Header->Collapsed && Header->LFBlock < Size )
  50.       return ( NULL ) ;
  51.  
  52.       /*  Yes.  So search block for free location  */
  53.  
  54.    offset  = HSIZE ;
  55.    while ( offset < Header->BytesUsed ) {
  56.       bptr  = (SUNIT *) Header + offset/SSIZE ;
  57.       bsize = *bptr & ~FREE ;
  58.       if ( (*bptr & FREE) && bsize >= Size ) {
  59.          *bptr = bsize ;
  60.          if ( bsize > Size ) {
  61.             offset += Size+SSIZE ;
  62.             *((SUNIT *)Header+offset/SSIZE) = (bsize - Size - SSIZE) | FREE ;
  63.             *bptr = Size ;
  64.             Header->Collapsed = FALSE ;
  65.          } ;
  66.          return ( (bptr+1) ) ;
  67.       } ;
  68.       offset += bsize+SSIZE  ;
  69.    } ;
  70.    return ( NULL ) ;
  71. }
  72.  
  73. int ExpandBlock ( Header, Size )
  74.  
  75.    HEADER *Header   ;
  76.    SUNIT   Size     ;
  77.  
  78. /*
  79.          +---------------------------------------+
  80.          |                                       |  
  81.          |  This procedure attempts to expand    |  
  82.          |  the given block by large enough      |  
  83.          |  to hold an allocation of size 'Size'.|  
  84.          |  If successful, a value of TRUE is    |  
  85.          |  returned.                            |  
  86.          |                                       |  
  87.          +---------------------------------------+
  88. */
  89.  
  90. {
  91.    SUNIT   *bptr    ;
  92.    SUNIT    offset  ;
  93.    SUNIT    bsize   ;
  94.    SUNIT    nu      ;
  95.    SUNIT    IncreaseBlockSize () ;
  96.  
  97.    if ( Header->HeaderSize != HSIZE )
  98.       return ( FALSE ) ;
  99.  
  100.       /*  Find last block in allocation  */
  101.  
  102.    offset  = HSIZE ;
  103.    while ( offset < Header->BytesUsed ) {
  104.       bptr    = (SUNIT *) Header + offset/SSIZE ;
  105.       bsize   = *bptr & ~FREE ;
  106.       offset += bsize+SSIZE  ;
  107.    } ;
  108.  
  109.       /*  If free, adjust Size appropriately to not have excessive
  110.           memory allocation.  */
  111.  
  112.    if ( *bptr & FREE )
  113.       Size -= bsize ;
  114.  
  115.    nu = MBSize * (( Size + SSIZE - 1 ) / MBSize + 1 ) ;
  116.    if ((long) Header->BytesUsed + (long) nu   > (long) MAXBLOCK ) {
  117.       nu =  NALLOC * ((MAXBLOCK - Header->BytesUsed)/NALLOC ) ;
  118.       if ( nu < Size )
  119.          return ( FALSE ) ;
  120.    } ; 
  121.  
  122.    nu = IncreaseBlockSize ( Header, nu ) ;
  123.    if ( nu < Size )
  124.       return ( FALSE ) ;
  125.    if ( *bptr & FREE ) {
  126.       *bptr += nu ;
  127.       if ( Header->Collapsed )
  128.          Header->LFBlock = max ( Header->LFBlock, (bsize+nu)) ;
  129.    }
  130.    else if ( nu > 0 ) {
  131.       bptr  = (SUNIT *) Header + offset/SSIZE ;
  132.       *bptr = (nu - SSIZE) | FREE ;
  133.       if ( Header->Collapsed )
  134.          Header->LFBlock = max ( Header->LFBlock, (nu-SSIZE)) ;
  135.    } ;
  136.    return ( TRUE ) ;
  137. }
  138.  
  139. HEADER *CheckBlock ( ap, offset )
  140.  
  141.    void    *ap     ;   /*  Pointer to allocation block      */
  142.    SUNIT   *offset ;   /*  Offset of ap - SSIZE (returned)  */
  143.  
  144. /*
  145.          +---------------------------------------+
  146.          |                                       |  
  147.          |  This procedure checks the block      |  
  148.          |  given to insure that it is a valid   |  
  149.          |  allocated block.                     |  
  150.          |                                       |  
  151.          +---------------------------------------+
  152. */
  153.  
  154. {
  155.    HEADER  *Header ;
  156.    int      i      ;
  157.    int      ok     ;
  158.  
  159.    FP_SEG (Header) = FP_SEG (ap) ;
  160.    FP_OFF (Header) = 0           ;
  161.    ok      = FALSE ;
  162.    *offset = 0 ;
  163.    for ( i = 0 ; i < NEntry ; i++ )
  164.       if ( Header             == AllocationTable [i].Header &&
  165.            Header->BytesUsed  == AllocationTable [i].Size      ) {
  166.          ok = TRUE ;
  167.          break ;
  168.       } ;
  169.    if ( ! ok || Header->HeaderSize != HSIZE )
  170.       return ( NULL ) ;
  171.  
  172.    *offset = FP_OFF (ap) - SSIZE ;
  173.    if ( *offset < HSIZE || *offset > Header->BytesUsed )
  174.       return ( NULL ) ;
  175.  
  176.    return ( Header ) ;
  177. }
  178.  
  179. void CollapseFreeBlocks ( Header )
  180.  
  181.    HEADER  *Header   ;
  182.  
  183. /*
  184.          +---------------------------------------+
  185.          |                                       |  
  186.          |  This procedure checks the block      |  
  187.          |  given for free allocations and       |  
  188.          |  collapses adjacent free blocks into  |  
  189.          |  single free blocks.                  |  
  190.          |                                       |  
  191.          +---------------------------------------+
  192. */
  193.  
  194. {
  195.    SUNIT    offset   ;
  196.    SUNIT    bsize    ;
  197.    SUNIT    nsize    ;
  198.    SUNIT    maxb     ;
  199.    SUNIT   *bptr     ;
  200.  
  201.       /*  If block has already been collapsed, return      */
  202.  
  203.    if ( Header->Collapsed )
  204.       return ;
  205.  
  206.       /*  Collapse ajacent free blocks into single blocks  */
  207.  
  208.    offset = HSIZE ;
  209.    maxb   =     0 ;
  210.    while ( offset < Header->BytesUsed ) {
  211.       bptr    = (SUNIT *) Header + offset/SSIZE ;
  212.       bsize   = *bptr & ~FREE ;
  213.       if ( *bptr & FREE ) {
  214.          maxb = max ( bsize, maxb ) ; 
  215.          if ((offset+bsize+SSIZE) < Header->BytesUsed ) {
  216.             if ((nsize = *(bptr+bsize/SSIZE+1)) & FREE )
  217.                *bptr += (nsize & ~FREE) + SSIZE ;
  218.             else
  219.                offset += bsize + SSIZE ;
  220.          }
  221.          else
  222.             break ; 
  223.       }
  224.       else
  225.          offset += bsize + SSIZE ;
  226.    } ;
  227.    Header->Collapsed = TRUE ;
  228.    Header->LFBlock   = maxb ;
  229. }
  230.  
  231. void FreeEmptyBlocks ( Header )
  232.  
  233.    HEADER  *Header   ;
  234.  
  235. /*
  236.          +---------------------------------------+
  237.          |                                       |  
  238.          |  This procedure proceeds backward     |  
  239.          |  from the highest allocated block     |  
  240.          |  and frees any totally empty ones     |  
  241.          |  back to the system.  It stops when   |  
  242.          |  it encounters a non-empty block.     |  
  243.          |                                       |  
  244.          +---------------------------------------+
  245. */
  246.  
  247. {
  248.    SUNIT   *bptr     ;
  249.  
  250.    if ( NEntry > 0 && Header == AllocationTable [NEntry-1]. Header ) {
  251.       bptr   = (SUNIT *) Header + HSIZE/SSIZE ;
  252.       while ( (*bptr &  FREE) &&
  253.               (*bptr & ~FREE) == (Header->BytesUsed-HSIZE-SSIZE) ) {
  254.          FreeBlock ( Header ) ;
  255.          AllocationTable [--NEntry].Header = NULL ;
  256.          AllocationTable [  NEntry].Size   = 0    ;
  257.          if ( NEntry == 0 )
  258.             break ;
  259.          Header = AllocationTable [NEntry-1].Header ;
  260.          bptr   = (SUNIT *) Header + HSIZE/SSIZE ;
  261.       } ;
  262.    } ;
  263. }
  264.  
  265. void NormalizeMBSize ()
  266.  
  267. /*
  268.          +---------------------------------------+
  269.          |                                       |  
  270.          |  This procedure normalizes the        |  
  271.          |  block allocation size variable just  |  
  272.          |  in case the user has set it to       |  
  273.          |  something wierd.                     |  
  274.          |                                       |  
  275.          +---------------------------------------+
  276. */
  277.  
  278. {
  279.  
  280.    if ( MBSize > MAXALLOC )
  281.       MBSize = MAXALLOC ;
  282.    else if ( MBSize < MINALLOC )
  283.       MBSize = MINALLOC ;
  284.    MBSize = NALLOC * ( ( MBSize - 1 ) / NALLOC + 1 ) ;
  285. }
  286.  
  287. HEADER *AllocateBlock ( Size )
  288.  
  289.    SUNIT Size  ;      /*  Number of bytes to allocate  */
  290.  
  291. /*
  292.          +---------------------------------------+
  293.          |                                       |  
  294.          |  Ask system for another block         |  
  295.          |                                       |  
  296.          +---------------------------------------+
  297. */
  298.  
  299. {
  300.    HEADER   *Header     ;
  301.    size_t    segment    ;
  302.    
  303.  
  304.       /*  Allocate a new block  */
  305.  
  306.    if ( _dos_allocmem ( (unsigned) Size / NALLOC, &segment ) != 0 )
  307.       return ( NULL ) ;
  308.  
  309.    FP_SEG (Header)     = segment  ;
  310.    FP_OFF (Header)     = 0        ;
  311.    Header->HeaderSize  = HSIZE    ;
  312.    Header->BytesUsed   = Size     ;
  313.    Header->Collapsed   = TRUE     ;
  314.    Header->LFBlock     = Size - HSIZE - SSIZE ;
  315.    *((SUNIT *) Header + HSIZE/SSIZE) = Header->LFBlock | FREE ;
  316.    
  317.    return ( Header ) ;
  318. }
  319.  
  320. static SUNIT IncreaseBlockSize ( Header, Size )
  321.  
  322.    HEADER *Header ;     /*  Pointer to header of block          */
  323.    SUNIT   Size   ;     /*  Number of bytes to expand block by  */
  324.  
  325. /*
  326.          +---------------------------------------+
  327.          |                                       |  
  328.          |  Ask system to expand given block.    |  
  329.          |  Returns number of bytes block was    |  
  330.          |  expanded by.                         |  
  331.          |                                       |  
  332.          +---------------------------------------+
  333. */
  334.  
  335. {
  336.    size_t   maxsize ;
  337.  
  338.    if ( _dos_setblock ( (Header->BytesUsed + Size)/NALLOC, FP_SEG (Header),
  339.                         &maxsize ) != 0 )
  340.       Size = 0 ;
  341.    else
  342.       Header->BytesUsed += Size ;
  343.    return ( Size ) ;
  344. }
  345.  
  346. static int FreeBlock ( Header )
  347.  
  348.    HEADER *Header ;     /*  Pointer to header of block          */
  349.  
  350. /*
  351.          +---------------------------------------+
  352.          |                                       |  
  353.          |  Free memory block to system.         |  
  354.          |                                       |  
  355.          +---------------------------------------+
  356. */
  357.  
  358. {
  359.    if ( _dos_freemem ( FP_SEG (Header) ) != 0 )
  360.       return ( FALSE ) ;
  361.    return ( TRUE ) ;
  362. }
  363.  
  364. #endif
  365. #endif
  366.  
  367.